using System.IO;
using Com.SharpZebra.Commands;
using NUnit.Framework;

namespace Com.SharpZebra.UnitTests.Commands
{
    [TestFixture]
    public class GraphicZebraCommandsTestFixture
    {
        private const string VALID_TEST_IMAGE_FILENAME = "testImage.pcx";

        [Test]
        public void GraphicCommandShouldStartWithStoringTheGraphicInMemory()
        {
            const string storeGraphicByNameCommand = "GK\"AN_IMAGE\"\n";
            string zebraInstruction = new GraphicZebraCommand(VALID_TEST_IMAGE_FILENAME, 0, 0).ToZebraInstruction();
            Assert.IsTrue(zebraInstruction.StartsWith(storeGraphicByNameCommand));
        }

        [Test]
        public void GraphicCommandShouldEndWithThePrintGraphicCommandGivenCoordinates()
        {
            int xCoordinate = 1;
            int yCoordinate = 5;
            string zebraInstruction =
                new GraphicZebraCommand(VALID_TEST_IMAGE_FILENAME, xCoordinate, yCoordinate).ToZebraInstruction();
            Assert.IsTrue(zebraInstruction.EndsWith("GG" + xCoordinate + "," + yCoordinate + ",\"AN_IMAGE\""));
        }

        [Test]
        public void GraphicComandShoudlLoadTheImageIntoMemory()
        {
            char[] fileAsChars = LoadCharsFromFile(VALID_TEST_IMAGE_FILENAME);
            string expectedCommandToSendToTheZebraPrinter =
                string.Format("GM\"AN_IMAGE\"{0}\n{1}\n", fileAsChars.Length, new string(fileAsChars));
            string zebraInstruction = new GraphicZebraCommand(VALID_TEST_IMAGE_FILENAME, 1, 1).ToZebraInstruction();

            Assert.IsTrue(zebraInstruction.Contains(expectedCommandToSendToTheZebraPrinter));
        }

        /* It seems that we have to read the bytes into memory (as bytes) first and then convert
         * them into characters. Simply read characters doesn't quite do it for us. Without doing
         * this properly, the Zebra printer will not print as expected
         */

        private static char[] LoadCharsFromFile(string fileName)
        {
            FileStream stream = new FileStream(fileName, FileMode.Open);
            BinaryReader binaryReader = new BinaryReader(stream);
            byte[] bytes = binaryReader.ReadBytes((int) stream.Length);
            char[] bytesAsChars = new char[bytes.Length];
            binaryReader.Close();
            stream.Close();
            for (int i = 0; i < bytes.Length; i++)
            {
                bytesAsChars[i] = (char) bytes[i];
            }
            return bytesAsChars;
        }
    }
}